package com.hd.service.doc.article.impl;

import com.hd.dao.BaseDao;
import com.hd.entity.Attach;
import com.hd.entity.doc.article.Doc;
import com.hd.entity.enums.DocTypeEnum;
import com.hd.service.AttachService;
import com.hd.service.doc.article.DocService;
import com.hd.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.*;

/**
* 文件管理
*/
@Service("docService")
public class DocServiceImpl implements DocService {
    @Autowired
    private BaseDao<Doc,String>docDao;
    @Autowired
    private AttachService attachService;

    /**
     * 创建文件、文件夹保存
     * @param doc
     */
    @Override
    public void save(Doc doc)throws Exception {
        doc.setCreateTime(new Date());
        if(StringUtils.isNull(doc.getId())) {
            doc.setId(UUID.randomUUID().toString());
        }
        doc.setName(getNewFileName(doc.getPid(),doc.getName(),doc.getType(),doc.getFileType()));
        if(doc.getType()==2){
            String uuid= StringUtils.getUUId();
            //文件
            Attach attach=new Attach();
            attach.setCreateTime(new Date());
            attach.setId(UUID.randomUUID().toString());
            attach.setName(doc.getName());
            attach.setType(doc.getFileType());
            String basePath= Const.BASE_UPLOAD_PATH+File.separator+
                    DateUtil.date2Str2(new Date());
            System.out.println("base="+basePath);
            File baseFile=new File(basePath);
            if(!baseFile.exists()){//创建基础文件夹
                baseFile.mkdirs();
            }
            String realPath= basePath+File.separator+uuid+doc.getName();
            String path=File.separator+DateUtil.date2Str2(new Date())+File.separator+uuid+doc.getName();
            File file = new File(realPath);
            if (!file.exists()) {
                file.createNewFile();
            }
            attach.setPath(path);
            attach.setSize("0");
            attachService.save(attach);
            doc.setAttachId(attach.getId());
        }
       docDao.save(doc);
    }

    /**
     * 更改名字
     * @param pid
     * @param name
     * @param type
     * @param fileType
     * @return
     */
    public String getNewFileName(String pid,String name,Integer type,String fileType){
        String hql="from Doc where pid=? and status=1";
        List<Doc>docs=docDao.find(hql,pid);
        if(docs.size()>0){
            for(Doc doc:docs){
                    System.out.println(1);
                    if (type.equals(doc.getType())) {
                        if (type == 2) {//文件
                            if (name.lastIndexOf(".") >= 0) {
                                name = name.substring(0, name.lastIndexOf(".")) + "." + fileType;
                            } else {
                                name = name + "." + fileType;
                            }
                            if (doc.getName().equals(name)) {
                                //名字相同，重命名
                                name = name.substring(0, name.lastIndexOf(".")) + DateUtil.datetime2Str(new Date()) + "." + fileType;
                            }
                        }
                        if (type == 1) {//文件夹
                            System.out.println(2);
                            if (doc.getName().equals(name)) {
                                //名字相同，重命名
                                name = name +  DateUtil.datetime2Str(new Date());
                            }
                        }
                    }
                }
            }
        return name;
    }
    /**
     * 用于上传保存
     * @param doc
     */
    @Override
    public void save2(Doc doc) {
        doc.setCreateTime(new Date());
        if(StringUtils.isNull(doc.getId())) {
            doc.setId(UUID.randomUUID().toString());
        }
        doc.setName(getNewFileName(doc.getPid(),doc.getName(),doc.getType(),doc.getFileType()));
        docDao.save(doc);
    }

    /**
     * 彻底删除
     * @param id
     */
    @Override
    public void delete(String id) {
        //1)遍历id的子文件
        List<Doc>docs=getByRoot(id);
        for(Doc doc:docs) {
            String hql = "delete from Doc where id=?";
            docDao.execute(hql, doc.getId());
        }
    }

    /**
     * 作废
     * @param id
     */
    @Override
    public void cancel(String id) {
        //1)遍历id的子文件
        List<Doc>docs=getByRoot(id);
        System.out.println(JsonUtil.toJson(docs));
        for(Doc doc:docs) {
            if(id.equals(doc.getId())){
                String hql = "update Doc set status=-1,pid=?,oldPid=?,path=?,lastUpdateTime=? where id=?";
                String path="/"+doc.getName();
                docDao.execute(hql,"",doc.getPid(),path, new Date(),doc.getId());
            }else {
                String hql = "update Doc set status=-1,oldPid=?,lastUpdateTime=? where id=?";
                docDao.execute(hql, doc.getPid(),new Date(),doc.getId());
            }
        }
    }
    @Override
    public  List<Doc> getByRoot(String id){
        List<Doc>docs=new ArrayList<>();
        getChilds(id,docs);
        return docs;
    }

    public void getChilds(String id, List<Doc>docs){
        Doc doc=get(id);
        docs.add(doc);
        String hql="from Doc where pid=?";
        List<Doc>docs1=docDao.find(hql,id);
        if(docs1.size()>0){
            for(Doc doc1:docs1){
                getChilds(doc1.getId(),docs);
            }
        }
    }
    /**
     * 还原
     * @param id
     */
    @Override
    public void updateBack(String id) {
        // String hql="update set status=1 where id=?";
        //docDao.execute(hql,id);
        //1)查询父类老的pid是否为空,不为空
        //11)若为作废，则将文件的父类ID置为空串，否则不改变父类ID
        //12)下面的子文件直接修改状态为可用即可
        Doc doc1=get(id);
        if(StringUtils.isNotNull(doc1.getOldPid())) {
            //1)查询父类老的pid是否为空,不为空
            //2)查询父机文件，判断是否作废
            Doc pDoc1=get(doc1.getOldPid());
            if(pDoc1.getStatus()==-1){
                //若为作废，则将文件的父类ID置为空串,oldPid置为空串，否则不改变父类ID
                String hql="update Doc set status=1, pid=?,oldPid=?,lastUpdateTime=? where id=?";
                docDao.execute(hql,"","",new Date(),id);
            }else{
                String hql="update Doc set status=1,pid=?,oldPid=?,lastUpdateTime=?  where id=?";
                docDao.execute(hql,doc1.getOldPid(),"",new Date(),id);
            }
        }else{
            //父类ID空，则直接修改状态即可
            String hql="update Doc set status=1 ,lastUpdateTime=? where id=?";
            docDao.execute(hql,new Date(),id);
        }
        //修改子类文件状态
        List<Doc>docs=getByRoot(id);
        for(Doc doc:docs) {
            String hql = "update Doc set status=1,lastUpdateTime=? where id=?";
            docDao.execute(hql,new Date(), doc.getId());
        }
    }
    /**
     * 通过父ID查询
     * @param pid
     * @return
     */
    @Override
    public List<Doc> findByPid(String pid,Integer status) {
        List<Doc>docs=new ArrayList<>();
        String hql="from Doc where pid=? and status=?";
        if(pid==null){
            hql="from Doc where pid is null and status=?";
            docs= docDao.find(hql,status);
        }else {
            docs = docDao.find(hql, pid,status);
        }
        return docs;
    }

    @Override
    public List<Doc> findByNameAndStatus(String name, Integer status) {
        String hql="from Doc where name like ? and status=?";
        return docDao.find(hql,"%"+name+"%",status);
    }

    @Override
    public Doc get(String id) {
        return docDao.get(Doc.class,id);
    }

    /**
     * 修改文件名名
     * @param id
     * @param name
     */
    @Override
    public void updateFileName(String id, String name) {
        Doc vo=get(id);
        //同一层类型相同的名字不能相同，相同则重命名
        String pid=vo.getPid();
        String hql="from Doc where pid=? and status=1";
        List<Doc>docs=docDao.find(hql,pid);
        if(docs.size()>0){
            for(Doc doc:docs){
                if(!id.equals(doc.getId())) {
                    System.out.println(1);
                    if (vo.getType().equals(doc.getType())) {
                        if (vo.getType() == 2) {//文件
                            String fileType = vo.getFileType();
                            if (name.lastIndexOf(".") >= 0) {
                                name = name.substring(0, name.lastIndexOf(".")) + "." + fileType;
                            } else {
                                name = name + "." + fileType;
                            }
                            if (doc.getName().equals(name)) {
                                //名字相同，重命名
                                name = name.substring(0, name.lastIndexOf(".")) + DateUtil.datetime2Str(new Date()) + "." + fileType;
                            }
                        }
                        if (vo.getType() == 1) {//文件夹
                            System.out.println(2);
                            if (doc.getName().equals(name)) {
                                //名字相同，重命名
                                name = name +  DateUtil.datetime2Str(new Date());
                            }
                        }
                    }
                }
            }
        }

        vo.setName(name);
        String path=vo.getPath().substring(0,vo.getPath().lastIndexOf("/"));
        vo.setPath(path+"/"+name);
        vo.setLastUpdateTime(new Date());
        docDao.update(vo);
    }

    @Override
    public void updatePid(String id, String pid) {
        Doc doc=get(id);
        if(StringUtils.isNotNull(pid)) {
            Doc pDoc = get(pid);
            String path = pDoc.getPath() + "/" + doc.getName();
            String hql="update Doc set pid=?,path=? where id=?";
            docDao.execute(hql,pid,path,id);
        }else{
            String path="/"+doc.getName();
            String hql="update Doc set pid='',path=? where id=?";
            docDao.execute(hql,path,id);
        }
    }

    @Override
    public void createDownloadFile(String id,String  rootPath)throws Exception {
        Map<String,Object>map=new HashMap<String,Object>();
        getChilds2(id,rootPath,map);
        if(map.size()>0){
            System.out.println(JsonUtil.toJson(map));
            for (Map.Entry<String, Object> entry : map.entrySet()) {
                File f=new File(entry.getValue().toString());
                if(!f.exists()){
                    f.createNewFile();
                }
                //复制文件
                Attach attach=attachService.get( entry.getKey());
                String oldPath=Const.BASE_UPLOAD_PATH+attach.getPath();
                FileUtil.copyFileUsingFileChannels(new File(oldPath),f);
            }
        }
    }

    /**
     * 递归创建文件夹和复制文件
     * @param id
     * @param rootPath
     */
    public void getChilds2(String id,String rootPath,Map<String,Object>map)throws Exception{
        Doc doc=get(id);
        String dir=rootPath;
        if(doc.getType()== DocTypeEnum.DIR.getType()){
             System.out.println("创建文件夹："+doc.getName());
             dir=rootPath+File.separator+doc.getName();
                File f=new File(dir);
                if(!f.exists()){
                    f.mkdirs();
                }
        }else{
            //创建文件
            String newfilePath=rootPath+File.separator+doc.getName();
            System.out.println("创建文件："+newfilePath);
            map.put(doc.getAttachId(),newfilePath);

        }
        String hql="from Doc where pid=? and status=1";
        List<Doc>docs1=docDao.find(hql,id);
        if(docs1.size()>0){
            for(Doc doc1:docs1){
                getChilds2(doc1.getId(),dir,map);
            }
        }
    }

    @Override
    public void updateFileSize(String id, String attachId, String srcSize, String newSize) {
        String hql="update Doc set size=?,lastUpdateTime=? where id=?";
        docDao.execute(hql,newSize,new Date(),id);
        attachService.updateFileSize(attachId,srcSize);
    }
}
